package com.lwd.util.collection;

import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.raycloud.erp.performance.common.utils.Assert;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class Maps {


    public static <K, V> Map<K, V> of(K k, V v) {
        return Collections.singletonMap(k, v);
    }

    public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2) {
        Map<K, V> map = new HashMap<>();
        map.put(k1, v1);
        map.put(k2, v2);

        return Collections.unmodifiableMap(map);
    }

    public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
        Map<K, V> map = new HashMap<>();
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);

        return Collections.unmodifiableMap(map);
    }

    public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
        Map<K, V> map = new HashMap<>();
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);

        return Collections.unmodifiableMap(map);
    }

    public static <K, NV, OV> Map<K, NV> transformValue(Map<K, OV> map, Function<OV, NV> valueGenerator) {
        return transform(map, new Function<K, K>() {
            @Override
            public K apply(K input) {
                return input;
            }
        }, valueGenerator);
    }

    public static <NK, OK, V> Map<NK, V> transformKey(Map<OK, V> map, Function<OK, NK> keyGenerator) {
        return transform(map, keyGenerator, new Function<V, V>() {
            @Override
            public V apply(V input) {
                return input;
            }
        });
    }

    public static <NK, NV, OK, OV> Map<NK, NV> transform(Map<OK, OV> map, Function<OK, NK> keyGenerator, Function<OV, NV> valueGenerator) {
        return transform(map, keyGenerator, valueGenerator, new Supplier<Map<NK, NV>>() {
            @Override
            public Map<NK, NV> get() {
                return new HashMap<>();
            }
        });
    }

    public static <NK, NV, OK, OV> Map<NK, NV> transform(Map<OK, OV> map, Function<OK, NK> keyGenerator,
                                                         Function<OV, NV> valueGenerator, Supplier<Map<NK, NV>> mapSupplier) {
        Assert.notNull(map);
        Assert.notNull(mapSupplier);
        Map<NK, NV> transformedMap = mapSupplier.get();

        for (Map.Entry<OK, OV> oldEntry : map.entrySet()) {
            NK newKey = keyGenerator.apply(oldEntry.getKey());
            NV newValue = valueGenerator.apply(oldEntry.getValue());
            transformedMap.put(newKey, newValue);
        }

        return transformedMap;
    }


}
